package org.example.learn_example.utils;

import org.example.learn_example.vo.MazePath;
import org.example.learn_example.vo.MazePoint;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class MazeUtils {


    public static final int[][] MAZE_ARRAY =
            {
                    { 1, 1, 1,-1, 1, 1, 1},
                    { 1, 1, 1, 1, 1, 1, 1},
                    { 1, 1,-1,-1, 1, 1, 1},
                    {-1, 1, 1,-1, 1, 1,-1},
                    { 1, 1,-1, 1, 1, 1, 1},
                    {-1, 1, 1, 1, 1,-1, 1},
                    { 1, 1, 1, 1,-1, 1, 1}
            };

    public static final int WIDTH=MAZE_ARRAY[0].length;
    public static final int HEIGHT=MAZE_ARRAY.length;

    public static int[][] copyMaze = MAZE_ARRAY.clone();

    public static int GET_PATH_COUNT=0;

    public static void main(String[] args) {
        MazePoint start=new MazePoint(1,1);
        MazePoint end=new MazePoint(WIDTH,HEIGHT);
        MazePath<MazePoint> mazePointMazePath=new MazePath<>();
        final MazePath<MazePoint> path = getPath(start, end, mazePointMazePath);
        System.out.println(path.toString());
        System.out.println(String.format("总计调用getPath次数为%d次！",GET_PATH_COUNT));
    }

    //    获取从开始到结束的路径
    public static MazePath<MazePoint> getPath(MazePoint start, MazePoint end, MazePath<MazePoint> mazePointMazePath) {
        GET_PATH_COUNT++;
        if (start.isValidPoint() && end.isValidPoint() && !start.isEquals(end)) {
            if (mazePointMazePath == null || mazePointMazePath.getLinkedList().size() == 0) {
                mazePointMazePath=new MazePath<>();
                mazePointMazePath.appendElement(start);
                System.out.println(String.format("put start point (%d,%d)",start.getX(),start.getY()));
            }
            final List<MazePoint> availableAdjoinPoint = getAvailableAdjoinPoint(start);
            for (int i = 0; i < availableAdjoinPoint.size(); i++) {
                MazePoint nextMazePoint = availableAdjoinPoint.get(i);
                System.out.println(String.format("check the point (%d,%d) is valid!",nextMazePoint.getX(),nextMazePoint.getY()));
                if (nextMazePoint.isEquals(end)) {
//            已经到终点   全部完成
                    mazePointMazePath.appendElement(nextMazePoint);
                    mazePointMazePath.setFinish(true);
                    System.out.println(String.format("finish the  point (%d,%d)",nextMazePoint.getX(),nextMazePoint.getY()));
                    return mazePointMazePath;
                } else if (mazePointMazePath.containsElement(nextMazePoint)) {
//                    形成环回到原来元素
                    System.out.println(String.format("error!!!! (%d,%d) is circle! continue to next!",nextMazePoint.getX(),nextMazePoint.getY()));
                    continue;
                } else {
//                    如果不包含环
                    mazePointMazePath.appendElement(nextMazePoint);
                    System.out.println(String.format("=======> (%d,%d) is valid! into the next level!",nextMazePoint.getX(),nextMazePoint.getY()));

                    final MazePath<MazePoint> resultPath = getPath(nextMazePoint, end, mazePointMazePath);
//                    代表这个两个点之间不可达
                    if (resultPath == null) {
                        mazePointMazePath.getLinkedList().remove(nextMazePoint);
                        int x = nextMazePoint.getX()-1;
                        int y = nextMazePoint.getY()-1;
                        copyMaze[y][x]=-999;
                        System.out.println(String.format("<======== DEAD!!! (%d,%d) is dead end!",nextMazePoint.getX(),nextMazePoint.getY()));
                    }else if (resultPath.isFinish()) {
                        return resultPath;
                    }
//                    return resultPath;
                }
            }
        }
        return null;
    }


    public static int getPointValue(MazePoint current) {
        int x = current.getX() - 1;
        int y = current.getY() - 1;
        int result = -999;
        if (current.isValidPoint()) {
            result = copyMaze[y][x];
        }
        return result;
    }

    /*
     * 获取对应点直接相邻的点
     * 在该函数里面定义了相邻点的定义
     * */
    public static List<MazePoint> getAvailableAdjoinPoint(MazePoint current) {
        List<MazePoint> resultList = new ArrayList<>();

        int x = current.getX();
        int y = current.getY();
        if (current.isValidPoint()) {
//      定义相邻点的关系
//      正上方点
            MazePoint upPoint = new MazePoint(x, y - 1);
//        正下方点
            MazePoint downPoint = new MazePoint(x, y + 1);
            //        正下方点
            MazePoint leftPoint = new MazePoint(x - 1, y);
            //        正下方点
            MazePoint rightPoint = new MazePoint(x + 1, y);
//      相邻点定义结束
//      在这里调整优先级优先向终点方向（右下角）探索
            if (y + 1 <= HEIGHT) {
                resultList.add(downPoint);
            }
            if (x + 1 <= WIDTH) {
                resultList.add(rightPoint);
            }

            if (y - 1 > 0) {
                resultList.add(upPoint);
            }

//            if (y + 1 <= MazePoint.HEIGHT) {
//                resultList.add(downPoint);
//            }

            if (x - 1 > 0) {
                resultList.add(leftPoint);
            }

//            if (x + 1 <= MazePoint.WIDTH) {
//                resultList.add(rightPoint);
//            }
            Iterator<MazePoint> iterator = resultList.iterator();
            while(iterator.hasNext()) {
                final MazePoint mazePoint = iterator.next();
                final int pointValue = getPointValue(mazePoint);
                if (pointValue < 0) {
//                    不能用remove  否则fori就不准确了
                    iterator.remove();
                }
            }
            return resultList;
        }
        return null;
    }

}
